<template>
  <BasicModal
    v-bind="$attrs"
    @register="registerModal"
    :title="getTitle"
    @ok="handleSubmit"
    :zIndex="20000"
    centered
  >
    <div class="flex flex-col h-full overflow-hidden">
      <div class="code_content">
        <div class="code_content_edit">
          <CodeMirror
            ref="codeEditor"
            :value="formulaStr"
            :labelNames="labelNames"
            @change="handleCodeEditorChange"
          />
        </div>
      </div>
      <div class="flex gap-5 justify-between p-5px flex-1">
        <Card title="表单字段" class="flex-1" :bodyStyle="bodyStyle" :headStyle="headStyle">
          <div class="flex flex-col">
            <div>
              <InputSearch
                v-model:value="fieldWord"
                placeholder="请输入"
                style="width: 100%"
                allowClear
                @change="fieldChange"
              />
            </div>
            <Tree
              v-model:expandedKeys="expandedKeysField"
              :tree-data="formGetFieldsData"
              v-model:selectedKeys="selectedKeysField"
              @select="handleSelectField"
              :height="400"
            >
              <template #title="{ title, fieldType, fieldTypeDesc }">
                <div
                  class="flex justify-between align-center mb-1 flex-1 overflow-auto pt-1 w-full"
                >
                  <div> {{ title }}</div>
                  <div v-if="fieldTypeDesc">
                    <Tag color="#2db7f5" v-if="fieldType == 0">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#0089ff" v-if="fieldType == 1">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#108ee9" v-if="fieldType == 2">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#2486b9" v-if="fieldType == 3">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#5c72ff" v-if="fieldType == 4">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#93d5dc" v-if="fieldType == 5">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#45b787" v-if="fieldType == 6">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#00b853" v-if="fieldType == 7">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#87d068" v-if="fieldType == 8">{{ fieldTypeDesc }}</Tag>
                    <Tag color="#2775b6" v-if="fieldType == 9">{{ fieldTypeDesc }}</Tag>
                  </div>
                </div>
              </template>
            </Tree>
          </div>
        </Card>
        <Card title="公式" class="flex-1" :bodyStyle="bodyStyle" :headStyle="headStyle">
          <div class="flex flex-col h-full">
            <div>
              <InputSearch
                v-model:value="funWord"
                placeholder="请输入"
                style="width: 100%"
                allowClear
                @change="funChange"
              />
            </div>
            <div class="flex-1 overflow-auto pt-1">
              <Tree
                v-model:expandedKeys="expandedKeys"
                :tree-data="exprListData"
                v-model:selectedKeys="selectedKeys"
                @select="handleSelect"
              >
                <template #title="{ title, typeDesc: fieldTypeDesc, type: fieldType }">
                  <div class="flex justify-between align-center mb-1 flex-1 overflow-auto pt-1">
                    <div>
                      {{ title }}
                    </div>
                    <div v-if="fieldTypeDesc">
                      <Tag color="#2db7f5" v-if="fieldType == 0">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#0089ff" v-if="fieldType == 1">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#108ee9" v-if="fieldType == 2">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#2486b9" v-if="fieldType == 3">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#5c72ff" v-if="fieldType == 4">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#93d5dc" v-if="fieldType == 5">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#45b787" v-if="fieldType == 6">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#00b853" v-if="fieldType == 7">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#87d068" v-if="fieldType == 8">{{ fieldTypeDesc }}</Tag>
                      <Tag color="#2775b6" v-if="fieldType == 9">{{ fieldTypeDesc }}</Tag>
                    </div>
                  </div>
                </template>
              </Tree>
            </div>
          </div>
        </Card>
        <Card
          :title="selectModel.label"
          class="flex-1"
          :bodyStyle="bodyStyle"
          :headStyle="headStyle"
        >
          <div class="h-400px overflow-auto">
            <div v-html="selectModel.description"></div>
          </div>
        </Card>
      </div>
    </div>
    <template #footer>
      <div class="flex justify-between items-center">
        <div class="text-red-400">
          <span v-if="!resultMsg.isAllow">*{{ resultMsg.msg }}</span>
        </div>
        <div>
          <a-button @click="handleClose()">取消</a-button>
          <a-button type="primary" @click="handleSubmit()">确定</a-button>
        </div>
      </div>
    </template>
  </BasicModal>
</template>

<script lang="ts" setup>
  import { ref } from 'vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { Card, Tag, Input, Tree } from 'ant-design-vue';
  import CodeMirror from './CodeMirror.vue';
  import { getExprList } from '/@/api/formDesign/formDesign';
  import { getFormGetFields, getExprGetFormsAndFields } from '/@/api/flowManage/flowManage';
  const InputSearch = Input.Search;
  import { useRouter } from 'vue-router';
  import { cloneDeep } from 'lodash-es';
  const { currentRoute } = useRouter();
  const emit = defineEmits(['success']);
  const fieldWord = ref('');
  const isUpdate = ref(false);
  const codeEditor = ref(null);
  const formulaStr = ref('');
  const resultMsg = ref({
    msg: '',
    isAllow: true,
  });

  const headStyle = {
    minHeight: '30px',
    padding: '0 5px',
  };
  const bodyStyle = {
    padding: '5px',
    height: 'calc(100% - 25px)',
    overflow: 'auto',
  };
  const fieldType = ref(1); //1是默认，只查当前表单字段 2是查所有表的表单字段

  const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
    setModalProps({
      confirmLoading: false,
      width: '70%',
      minHeight: 400,
    });
    fieldType.value = data.fieldType || 1;
    isUpdate.value = !!data?.isUpdate;
    selectModel.value = {};
    formulaStr.value = data.expr || '';
    await getFormGetFieldsData();
    await getExprListData();
    resultMsg.value.isAllow = true;
  });
  const getTitle = ref('公式编辑器');

  function insertContent(value, type) {
    codeEditor.value?.insertContent(value, type);
    // const from = editor.value.getCursor();
    // if (type === 'variable') {
    //   editor.value.replaceSelection(value);
    //   const to = editor.value.getCursor();
    //   markText(from, to, value, 'cm-field');
    // } else if (type === 'func') {
    //   editor.value.replaceSelection(`${value}()`);
    //   const to = editor.value.getCursor();
    //   markText(from, { line: to.line, ch: to.ch - 2 }, value, 'cm-func');
    //   editor.value.setCursor({ line: to.line, ch: to.ch - 1 });
    // } else if (typeof value === 'string') {
    //   editor.value.replaceSelection(value);
    // }
    // editor.value.focus();
  }

  // 校验计算式
  function checkCalcExpressionValid(expression) {
    resultMsg.value.msg = '';
    const word_regex = /[\u4e00-\u9fa5\xa1-\xff]/g; // 前为utf8中文范围，后为gb2312中文范围
    // 空字符串检查
    if (expression === '' || expression == null || !expression) {
      resultMsg.value.msg = '字符串不能为空';
      return false;
    }

    // 移除空格并处理数字前的多余零，但对于小数点前的零不处理
    expression = expression.replace(/\s/g, '').replace(/(^|[^.\d])0+(?=\d)/g, '$1');

    // 检查非法字符（只允许数字、括号、加减乘除运算符、等号和小数点）
    if (/[^A-Z0-9a-z+=\-_*/(/).",#]/.test(expression)) {
      if (!word_regex.test(expression)) {
        resultMsg.value.msg =
          '检查非法字符（只允许汉字、数字、括号、加减乘除运算符、等号和小数点）';
        return false;
      }
    }
    // 检查连续三个或更多减号
    if (/---+/.test(expression)) {
      resultMsg.value.msg = '检查是否有连续减号';
      return false;
    }
    // 替换所有连续的两个减号为单个加号
    // expression = expression.replace(/--/g, '+');

    // // 检查非法字符（包括英文字母、逗号）、连续运算符（除了减号）、错误的括号或运算符位置，以及运算符后跟等号的情况
    // if (
    //   /[a-zA-Z,]|[\+\*\/]{2,}|[\+\-\*\/]=|[\(\)\[\]]{2}|[\+\*\/\.]\)|\([\+\*\/]|[\+\*\/\.]\[|\][\+\*\/\.]|^[\+\*\/\.]|[\+\*\/\.]$/.test(
    //     expression,
    //   )
    // ) {
    //   if (!word_regex.test(expression)) {
    //     resultMsg.value.msg =
    //       '检查非法字符（包括英文字母、逗号）、连续运算符（除了减号）、错误的括号或运算符位置，以及运算符后跟等号的情况';
    //     return false;
    //   }
    // }
    // 检查数字后直接跟左括号，或右括号后直接跟数字的情况（隐式乘法）
    if (/\d\(|\)\d/.test(expression)) {
      resultMsg.value.msg = '检查数字后直接跟左括号，或右括号后直接跟数字的情况';
      return false;
    }
    // 检查括号是否配对
    let brackets = { '(': ')', '[': ']' };
    let stack = [];
    for (let char of expression) {
      if (brackets[char]) {
        stack.push(brackets[char]);
      } else if (char === ')' || char === ']') {
        if (stack.pop() !== char) {
          resultMsg.value.msg = '检查括号是否配对';
          return false;
        }
      }
    }
    if (stack.length > 0) {
      resultMsg.value.msg = '检查括号是否配对';
      return false;
    }
    // 检查数字格式（例如避免多个连续的小数点）
    if (/(\.\d*){2,}/.test(expression)) {
      resultMsg.value.msg = '检查数字格式（例如避免多个连续的小数点）';
      return false;
    }
    // 防止单个运算符
    if (/^[+\-*/.]$/.test(expression) === true) {
      resultMsg.value.msg = '防止单个运算符';
      return false;
    }

    return true;
  }

  async function handleSubmit() {
    try {
      setModalProps({ confirmLoading: true });
      const res = await checkCalcExpressionValid(formulaStr.value);
      resultMsg.value.isAllow = res;
      if (res) {
        emit('success', formulaStr.value);
        closeModal();
      }
    } finally {
      setModalProps({ confirmLoading: false });
    }
  }

  function handleClose() {
    closeModal();
  }
  const formGetFieldsData = ref<any[]>([]);
  const oldFormGetFieldsData = ref<Recordable[]>([]);
  const selectedKeysField = ref([]);
  const expandedKeysField = ref<any[]>([]);
  const labelNames = ref<string[]>([]);
  //获取目标字段
  const getFormGetFieldsData = async () => {
    try {
      const { query } = currentRoute.value;
      if (query?.formCode) {
        labelNames.value = [];
        let num = 300;
        if (fieldType.value == 1) {
          await getFormGetFields({ formCode: query.formCode }).then((res) => {
            formGetFieldsData.value = res || [];
            formGetFieldsData.value.forEach((item) => {
              item.layer = 1;
              item.key = item.name;
              item.title = item.title;
              item.newLabel = item.title;
              labelNames.value.push(item.title);
              item.children = [];
            });

            let it = {
              title: '记录状态',
              newLabel: '记录状态',
              key: 'cws_staus',
              layer: 1,
              fieldType: 2,
              fieldTypeDesc: '整数型',
            };
            labelNames.value.push(it.title);
            formGetFieldsData.value.push(it);

            oldFormGetFieldsData.value = cloneDeep(formGetFieldsData.value);
          });
        } else if (fieldType.value == 2) {
          await getExprGetFormsAndFields({ formCode: query.formCode }).then((res) => {
            formGetFieldsData.value = res || [];
            formGetFieldsData.value.forEach((item, index) => {
              item.layer = 2;
              item.key = ++num;
              item.title = item.label;
              item.newLabel = item.label;
              labelNames.value.push(item.label);
              if (item.children && item.children.length) {
                item.children.forEach((el) => {
                  el.layer = 2;
                  el.key = ++num;
                  el.title = el.label;
                  el.newLabel = el.label;
                  if (true || index != 0) {
                    el.newLabel = `${item.label}.${el.label}`;
                    labelNames.value.push(`${item.label}.${el.label}`);
                  } else {
                    labelNames.value.push(el.label);
                  }
                });
              } else {
                item.children = [];
              }
            });
            if (formGetFieldsData.value && formGetFieldsData.value.length) {
              expandedKeysField.value.push(formGetFieldsData.value[0].key);
            }
            oldFormGetFieldsData.value = cloneDeep(formGetFieldsData.value);
          });
        }
      }
    } catch (err) {
      console.error('getFormGetFields', err);
    }
  };
  //字段树选中
  function handleSelectField(val, trc) {
    selectedKeysField.value = [];
    if (val.length) {
      const { newLabel } = trc.node.dataRef;
      insertContent(newLabel, 'variable');
    }
  }

  //字段查询
  function fieldChange() {
    if (fieldWord.value) {
      formGetFieldsData.value = oldFormGetFieldsData.value.filter((item) =>
        item.title.toLowerCase().includes(fieldWord.value.toLowerCase()),
      );
    } else {
      formGetFieldsData.value = [...oldFormGetFieldsData.value];
    }
    // if (fieldWord.value) {
    //   const filterFn = (node) => node.label.toLowerCase().includes(fieldWord.value.toLowerCase());
    //   formGetFieldsData.value = filterTreeNodes(oldFormGetFieldsData.value, filterFn);
    //   expandedKeysField.value = formGetFieldsData.value.map((item) => item.key);
    // } else {
    //   formGetFieldsData.value = cloneDeep(oldFormGetFieldsData.value);
    //   expandedKeysField.value = [];
    // }
  }

  const selectedKeys = ref([]);
  const expandedKeys = ref<any[]>([]);
  const exprListData = ref<any[]>([]);
  const oldExprListData = ref<any[]>([]);
  const selectModel = ref<any>({});
  //获取公式
  async function getExprListData() {
    expandedKeys.value = [];
    await getExprList().then((res) => {
      exprListData.value = res;
      exprListData.value.forEach((item) => {
        item.layer = 1;
        item.key = item.value;
        item.title = item.label;
        item.disabled = true;
        expandedKeys.value.push(item.key);
        if (item.children && item.children.length) {
          item.children.forEach((el) => {
            el.layer = 2;
            el.key = el.value;
            el.title = el.value;
          });
        } else {
          item.children = [];
        }
      });
      oldExprListData.value = [...exprListData.value];
    });
  }
  //树选中
  function handleSelect(val, trc) {
    selectedKeys.value = [];
    selectModel.value = trc.node.dataRef;
    insertContent(selectModel.value.value, 'func');
  }

  function handleCodeEditorChange(val) {
    formulaStr.value = val;
  }

  function filterTreeNodes(nodes, filterFn) {
    return nodes
      .map((node) => {
        const newNode = { ...node };
        if (newNode.children) {
          newNode.children = filterTreeNodes(newNode.children, filterFn);
        }
        return newNode;
      })
      .filter((node) => filterFn(node) || (node.children && node.children.length > 0));
  }

  const funWord = ref('');
  //函数列表
  function funChange() {
    if (funWord.value) {
      const filterFn = (node) => node.label.toLowerCase().includes(funWord.value.toLowerCase());
      exprListData.value = filterTreeNodes(oldExprListData.value, filterFn);
      expandedKeys.value = exprListData.value.map((item) => item.value);
    } else {
      exprListData.value = [...oldExprListData.value];
    }
    expandedKeys.value = exprListData.value.map((item) => item.value);
  }

  const getPopupContainer = (triggerNode) => triggerNode?.parentNode;
</script>

<style lang="less" scoped>
  .code_content {
    text-align: left;
    width: 100%;
    padding: 5px;
    .code_content_edit {
      height: 200px;
      border-radius: 6px;
      border: 1px solid #e8e9eb;
    }
  }
  .code_content_title {
    background-color: #fafafa;
    height: 30px;
    vertical-align: center;
    line-height: 30px;
    padding-left: 10px;
    border-radius: 4px 4px 0 0;
    border-bottom: none;
  }
  :deep(.ant-card-head-title) {
    padding: 0;
  }
  :deep(.ant-tree) {
    height: 400px;
    overflow: auto;
  }
  :deep(.ant-tree-treenode) {
    width: 100%;
  }
  :deep(.ant-tree-node-content-wrapper) {
    flex: 1;
  }
  :deep(.CodeMirror-sizer) {
    margin-left: 30px !important;
  }
  :deep(.CodeMirror-linenumber) {
    min-width: 10px !important;
    width: 10px !important;
  }
  :deep(.CodeMirror-gutters) {
    left: 0 !important;
  }
</style>
